﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using Go;

namespace fhs
{
    public partial class CmdViewForm : Form
    {
        Dictionary<CmdName.MC, DataGridViewRow> mcstate = new Dictionary<CmdName.MC, DataGridViewRow>();
        chan<CmdName.MC> changeChan;
        generator refreshState;

        public CmdViewForm()
        {
            InitializeComponent();
        }

        private void CmdViewForm_Load(object sender, EventArgs e)
        {
            foreach (CmdName.MC item in typeof(CmdName.MC).GetEnumValues())
            {
                if (CmdName.mcs.ContainsKey(item))
                {
                    DataGridViewRow newRows = new DataGridViewRow();
                    newRows.CreateCells(dataGridView1);
                    newRows.Cells[dataGridView1.Columns["名称"].Index].Value = item.ToString();
                    newRows.Cells[dataGridView1.Columns["地址"].Index].Value = CmdName.mcs[item].addr.ToString();
                    newRows.Cells[dataGridView1.Columns["类型"].Index].Value = CmdName.mcs[item].type.ToString();
                    newRows.Cells[dataGridView1.Columns["数值"].Index].Value = "- - -";
                    if (CmdName.mcs[item].readOnly)
                    {
                        newRows.Cells[dataGridView1.Columns["数值"].Index].Style.BackColor = Color.Yellow;
                    }
                    dataGridView1.Rows.Add(newRows);
                    mcstate[item] = newRows;
                }
            }
            changeChan = chan<CmdName.MC>.make(GlobalData.mainStrand, 0);
            generator.go(out refreshState, GlobalData.mainStrand, RefreshAction);
        }

        private void CmdViewForm_FormClosing(object sender, FormClosingEventArgs e)
        {
            e.Cancel = true;
            Hide();
        }

        private void CmdViewForm_FormClosed(object sender, FormClosedEventArgs e)
        {
            refreshState?.stop();
        }

        private async Task RefreshAction()
        {
            if (0 == mcstate.Count)
            {
                return;
            }
            generator.children update = new generator.children();
            update.go(async delegate ()
            {
                while (true)
                {
                    CmdName.MC mc = await changeChan.receive();
                    CmdName.Addr addr = CmdName.mcs[mc];
                    if (addr.readOnly)
                    {
                        continue;
                    }
                    int data = 0;
                    try
                    {
                        switch (addr.type)
                        {
                            case CmdName.Type.WORD:
                                data = (short)await CmdName.mc.Read(addr.addr); break;
                            case CmdName.Type.DWORD:
                                data = (int)await CmdName.mc.Read32(addr.addr); break;
                            default:
                                continue;
                        }
                    }
                    catch (generator.stop_exception) { throw; }
                    catch (Exception)
                    {
                        continue;
                    }
                    int number = 0;
                    if (await generator.send_control(this, delegate ()
                    {
                        CmdInpuForm input = new CmdInpuForm(data, addr.max, addr.min);
                        input.ShowDialog();
                        number = input.number;
                        return input.ok;
                    }))
                    {
                        try
                        {
                            LogMgr.File($"手动给PLC {mc}:{addr.addr}-{addr.type} 设置了 {number}");
                            switch (addr.type)
                            {
                                case CmdName.Type.WORD:
                                    await CmdName.mc.Write(addr.addr, (ushort)number); break;
                                case CmdName.Type.DWORD:
                                    await CmdName.mc.Write32(addr.addr, (uint)number); break;
                            }
                        }
                        catch (generator.stop_exception) { throw; }
                        catch (Exception) { }
                    }
                }
            });
            int numberIndex = dataGridView1.Columns["数值"].Index;
            Dictionary<CmdName.MC, generator.child> mcAction = new Dictionary<CmdName.MC, generator.child>();
            while (true)
            {
                if (!Visible)
                {
                    await generator.sleep(100);
                    continue;
                }
                foreach (var item in mcstate)
                {
                    CmdName.Addr addr = CmdName.mcs[item.Key];
                    string dataStr = null;
                    try
                    {
                        switch (addr.type)
                        {
                            case CmdName.Type.WORD:
                                dataStr = ((short)await CmdName.mc.Read(addr.addr)).ToString(); break;
                            case CmdName.Type.DWORD:
                                dataStr = ((int)await CmdName.mc.Read32(addr.addr)).ToString(); break;
                            default:
                                dataStr = "- - -"; break;
                        }
                    }
                    catch (generator.stop_exception) { throw; }
                    catch (Exception)
                    {
                        dataStr = "- - -";
                    }
                    var cell = item.Value.Cells[numberIndex];
                    if (dataStr != cell.Value.ToString())
                    {
                        cell.Value = dataStr;
                        generator.child hasAction;
                        if (mcAction.TryGetValue(item.Key, out hasAction))
                        {
                            await update.stop(hasAction);
                        }
                        mcAction[item.Key] = update.tgo(async delegate ()
                        {
                            Color defaultColor = addr.readOnly ? Color.Yellow : Color.White;
                            try
                            {
                                for (int i = 0; i < 2; i++)
                                {
                                    cell.Style.BackColor = Color.LightBlue;
                                    await generator.sleep(250);
                                    cell.Style.BackColor = defaultColor;
                                    await generator.sleep(250);
                                }
                            }
                            finally
                            {
                                cell.Style.BackColor = defaultColor;
                            }
                        });
                    }
                }
            }
        }

        private void dataGridView1_CellDoubleClick(object sender, DataGridViewCellEventArgs e)
        {
            if (e.ColumnIndex == dataGridView1.Columns["数值"].Index)
            {
                CmdName.MC mc = (CmdName.MC)(-1);
                if (StringToEnum.Convert(dataGridView1.Rows[e.RowIndex].Cells[dataGridView1.Columns["名称"].Index].Value.ToString(), ref mc))
                {
                    changeChan.try_post(mc);
                }
            }
        }
    }
}
